package members

import (
	"net/http"
	"github.com/gorilla/websocket"
	"adai.design/homeserver/log"
	"errors"
)

type PackageObserver interface {
	HandleMemberPkg(pkg *MessagePkg)
}

type receptions struct {
	memberships 	map[string][]*reception

	register		chan *reception
	unregister		chan *reception

	recPkg 			chan *MessagePkg
	sendPkg 		chan *MessagePkg

	observers 		[]PackageObserver

	upgrader 		websocket.Upgrader
	address 		string
	end 			chan bool
}


func (rs *receptions) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	c, err := rs.upgrader.Upgrade(response, request, nil)
	if err != nil {
		log.Error("upgrade: ", err)
		return
	}

	r := reception{conn: c}
	go r.start(rs)
}

// 由于一个账号同时在iphone/ipad/android/macbook上进行登录
// 同一种类型的设备，只允许一台设备在线
func (rs *receptions) start() {
	rs.register = make(chan *reception, 10)
	rs.unregister = make(chan *reception, 10)
	rs.recPkg = make(chan *MessagePkg, 10)
	rs.sendPkg = make(chan *MessagePkg, 10)
	rs.memberships = make(map[string][]*reception, 0)

	for {
		select {
		case c, ok := <- rs.register:
			if ok {
				if c.m.Phone != "" {
					log.Info("account(%s) dev_type(%s) online", c.m.Phone, c.mc.DevType)
				} else {
					log.Info("account(%s) dev_type(%s) online", c.m.Email, c.mc.DevType)
				}
				log.Debug("reception info(%s:%s) online", c.m.Id, c.mc.Session)
				if cs, ok := rs.memberships[c.m.Id]; ok {
					for i, v := range cs {
						if v.mc.Session == c.mc.Session {
							cs[i].disconnect()
						} else if v.mc.DevType == c.mc.DevType {
							cs[i].logout()
						}
					}
					rs.memberships[c.m.Id] = append(cs, c)
				} else {
					rs.memberships[c.m.Id] = []*reception{c}
				}
			}

		case c, ok := <- rs.unregister:
			if ok {
				if c.m.Phone != "" {
					log.Info("account(%s) dev_type(%s) offline", c.m.Phone, c.mc.DevType)
				} else {
					log.Info("account(%s) dev_type(%s) offline", c.m.Email, c.mc.DevType)
				}
				log.Debug("reception info(%s:%s) offline", c.m.Id, c.mc.Session)
				if cs, ok := rs.memberships[c.m.Id]; ok {
					for i, v := range cs {
						if v == c {
							rs.memberships[c.m.Id] = append(cs[:i], cs[i+1:]...)
						}
					}
				}
			}

		case pkg, ok := <-rs.sendPkg:
			if ok {
				if clients, ok := rs.memberships[pkg.Ctx.MemberId]; ok {
					// 通知所有用户
					if pkg.Ctx.Session == "" {
						for _, client := range clients {
							client.task <- pkg.Msg
						}
					} else {
						// 通知给制定用户
						for _, client := range clients {
							if client.mc.Session == pkg.Ctx.Session {
								client.task <- pkg.Msg
								break
							}
						}
					}
				}
			}

		case pkg, ok := <-rs.recPkg:
			if ok {
				for _, observer := range rs.observers {
					observer.HandleMemberPkg(pkg)
				}
			}

		}
	}
}

var workers = &receptions{}

func SendPackage(pkg *MessagePkg) error {
	if pkg == nil || pkg.Ctx == nil || pkg.Msg == nil {
		return errors.New("message package format error")
	}
	if workers.sendPkg == nil {
		return errors.New("receptions service did not start ")
	}
	workers.sendPkg <- pkg
	return nil
}

func AddObserver(ob PackageObserver) error {
	workers.observers = append(workers.observers, ob)
	return nil
}

func RemoveObserver(ob PackageObserver) error {
	for i, observer := range workers.observers {
		if observer == ob {
			workers.observers = append(workers.observers[:i], workers.observers[i+1:]...)
			return nil
		}
	}
	return nil
}


